package com.springboot.es.controller;

import com.springboot.es.entity.Book;
import com.springboot.es.repository.BookRepository;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;


@RestController
@Slf4j
public class TestController {

    @Autowired
    BookRepository bookRepository;

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;


    /**
     * 创建索引
     */
    @GetMapping(value = "/createIndex")
    public void createIndex(){
        elasticsearchTemplate.createIndex(Book.class);
    }

    /**
     * 创建文档
     */
    @GetMapping(value = "/createBook")
    public String createBook(String id){
        String name = "遮天";
        String title = "冰冷与黑暗并存的宇宙深处，九具庞大的龙尸拉着一口青铜古棺，亘古长存";
        String desc = "本书以九龙拉棺为引子，带出一个庞大的洪荒玄幻世界，引出上古神话的遗秘，卷帙浩阔，设定繁杂，人物众多。";
        bookRepository.save(new Book(id,name,title,desc));
        return "add success";
    }

    /**
     * 创建多个book文档
     */
    @GetMapping(value = "/createManyBook")
    public void createManyBook(){
        List<Book> list = Arrays.asList(
                new Book("76521","遮天","冰冷与黑暗并存的宇宙深处，九具庞大的龙尸拉着一口青铜古棺，亘古长存,木九天","本书以九龙拉棺为引子，带出一个庞大的洪荒玄幻世界，引出上古神话的遗秘，卷帙浩阔，设定繁杂，人物众多。"),
                new Book("77521","完美世界，木九天","心潮澎湃，无限幻想，迎风挥击千层浪，少年不败热血！","一粒尘可填海，一根草斩尽日月星辰，弹指间天翻地覆，群雄并起，万族林立，诸圣争霸，乱天动地。问苍茫大地，谁主沉浮？！"),
                new Book("78521","神墓","一个死去万载岁月的平凡青年从远古神墓中复活而出……","穿越了宇宙洪荒，凝练了天地玄黄，纵使摆脱六道轮回，也难逃那天地动荡，木九天"),
                new Book("79521","圣墟","在破败中崛起，在寂灭中复苏。沧海成尘，雷电枯竭……","在破败中崛起，在寂灭中复苏，沧海成尘，雷电枯竭，那一缕幽雾又一次临近大地，世间的枷锁被打开了，一个全新的世界就此揭开神秘的一角")
        );
        list.stream().forEach(book -> bookRepository.save(book));
    }

    /**
     * 根据id删除book文档
     */
    @GetMapping(value = "/deleteById")
    public void deleteById(String id){
        bookRepository.deleteById(id);
    }

    /**
     * 删除全部
     */
    @GetMapping(value = "/deleteAll")
    public void deleteAll(){
        bookRepository.deleteAll();
    }

    /**
     * 修改book文档
     */
    @GetMapping(value = "/updateBook")
    public void updateBook(){
        Book book = bookRepository.findById("").get();
        bookRepository.save(new Book(book.getId(),"修改","",""));
    }

    /**
     * 通过id查询book文档
     */
    @GetMapping(value="getBookById")
    public String getBookById(String id){
        Book book  = bookRepository.findById(id).get();
        return book.getName();
    }

    /**
     * 查询所有book文档
     */
    @GetMapping(value = "/findAll")
    public List<Book> test3(){
        Iterable<Book> result = bookRepository.findAll();
        Iterator<Book> resu = result.iterator();
        List<Book> list = new ArrayList<>();
        while (resu.hasNext()){
            list.add(resu.next());
        }
        return list;
    }

    /**
     * 使用query_string
     * @param search
     */
    @GetMapping(value = "/find1")
    public void find1(String search){
        // 不添加defaultField("name")，默认全局搜索，添加defaultField("name")之后，只搜索name字段
        QueryStringQueryBuilder builder = new QueryStringQueryBuilder(search).defaultField("name");
        Iterable<Book> bookIterable = bookRepository.search(builder);
        Iterator<Book> bookIterator = bookIterable.iterator();
        List<Book> books = new ArrayList<>();
        while (bookIterator.hasNext()){
             books.add(bookIterator.next());
        }
        books.stream().forEach(System.out::println);
    }

    /*FilterFunctionBuilder filterFunctionBuilder1 = new FilterFunctionBuilder(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("name",search)),ScoreFunctionBuilders.weightFactorFunction(50));
    FilterFunctionBuilder filterFunctionBuilder2 = new FilterFunctionBuilder(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("desc",search)),ScoreFunctionBuilders.weightFactorFunction(5));
    FilterFunctionBuilder filterFunctionBuilder3 = new FilterFunctionBuilder(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("desc",search)),ScoreFunctionBuilders.weightFactorFunction(1));
    FilterFunctionBuilder[] filterFunctionBuilders = new FilterFunctionBuilder[]{filterFunctionBuilder1,filterFunctionBuilder2,filterFunctionBuilder3};
    FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(filterFunctionBuilders);*/
    /**
     *  设置权重查询
     */
    @GetMapping(value = "/find2")
    public void find2(String search){
        // 分页设置
        Pageable pageable = PageRequest.of(0, 10);
        // 排序设置
        FunctionScoreQueryBuilder functionScoreQueryBuilder2 = QueryBuilders.functionScoreQuery(
                QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("name",search)), ScoreFunctionBuilders.weightFactorFunction(10));
        // 设置查询（分页、排序）
        NativeSearchQuery query = new NativeSearchQueryBuilder().withPageable(pageable).withQuery(functionScoreQueryBuilder2).build();
        // 匹配结果
        Page<Book> bookPage = bookRepository.search(query);
        // 获取list
        List<Book> books = bookPage.getContent();
        // 遍历
        books.stream().forEach(System.out::println);
    }

    /**
     * 多字段匹配查询
     */
    @GetMapping(value = "/searchMulti")
    public void searchMulti(){
        QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery("","","","");
    }

    /**
     * 短语查询，整个短语查询，不拆词
     */
    @GetMapping(value = "/searchPhraseMatch")
    public void searchPhraseMatch(String search){
        QueryBuilder queryBuilder = QueryBuilders.matchPhraseQuery("title",search);
        Pageable pageable = PageRequest.of(0,5);
        Page<Book> books = bookRepository.search(queryBuilder,pageable);
        List<Book> list = books.getContent();
        list.stream().forEach(System.out::println);
    }

    /**
     * ik-smart 分词查询
     */
    @GetMapping(value = "/searchIkSmart")
    public void searchIkSmart(String search){
        QueryBuilder queryBuilder = QueryBuilders.matchQuery("title",search);
        Pageable pageable = PageRequest.of(0,5);
        Page<Book> books = bookRepository.search(queryBuilder,pageable);
        List<Book> list = books.getContent();
        list.stream().forEach(System.out::println);
    }

    /**
     * 组合查询
     */
    @GetMapping(value = "/searchBool")
    public void searchBool(int score){
        QueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("title","帅哥"))
                .should(QueryBuilders.matchQuery("title","存在"))
                .mustNot(QueryBuilders.matchQuery("title","叶凡"))
                .filter(QueryBuilders.rangeQuery("id").lte(score));

        Iterable<Book> iterable = bookRepository.search(queryBuilder);
        Iterator<Book> iterator = iterable.iterator();
        while (iterator.hasNext()){
            Book book = iterator.next();
            log.info(book.getId() + "======" + book.getDesc() + "=====" + book.getTitle());
        }
    }

    // querystring  查询or的方式 NativeSearchQuery
    @GetMapping(value = "/test6")
    public void test6() {
        QueryBuilder queryBuilder = QueryBuilders.termQuery("","");
        Pageable pageable = PageRequest.of(0,15);
        bookRepository.findAll(pageable);
        QueryBuilders.queryStringQuery("").defaultField("");

        NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(QueryBuilders.queryStringQuery("").defaultField("")).withPageable(pageable)
                .build();
        //template.queryForList(query,Book.class);
    }
}
